home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectInput / Mouse / mouse.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  26.3 KB  |  691 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Mouse.cpp
  3. //
  4. // Desc: The Mouse sample show how to use a DirectInput mouse device and 
  5. //       the differences between cooperative levels and data styles. 
  6. //
  7. // Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define STRICT
  10. #include <tchar.h>
  11. #include <windows.h>
  12. #include <basetsd.h>
  13. #include <dinput.h>
  14. #include <stdio.h>
  15. #include "resource.h"
  16.  
  17.  
  18.  
  19.  
  20. //-----------------------------------------------------------------------------
  21. // Function-prototypes
  22. //-----------------------------------------------------------------------------
  23. INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  24. HRESULT OnInitDialog( HWND hDlg );
  25. VOID    UpdateUI( HWND hDlg );
  26. HRESULT OnCreateDevice( HWND hDlg );
  27. HRESULT ReadImmediateData( HWND hDlg );
  28. HRESULT ReadBufferedData( HWND hDlg );
  29. VOID    FreeDirectInput();
  30.  
  31.  
  32.  
  33.  
  34. //-----------------------------------------------------------------------------
  35. // Defines, constants, and global variables
  36. //-----------------------------------------------------------------------------
  37. #define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
  38. #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
  39.  
  40. #define SAMPLE_BUFFER_SIZE  16      // arbitrary number of buffer elements
  41. LPDIRECTINPUT8       g_pDI    = NULL;         
  42. LPDIRECTINPUTDEVICE8 g_pMouse = NULL;     
  43.  
  44.  
  45.  
  46.  
  47. //-----------------------------------------------------------------------------
  48. // Name: WinMain()
  49. // Desc: Entry point for the application.  Since we use a simple dialog for 
  50. //       user interaction we don't need to pump messages.
  51. //-----------------------------------------------------------------------------
  52. int WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int )
  53. {
  54.     // Display the main dialog box.
  55.     DialogBox( hInst, MAKEINTRESOURCE(IDD_MOUSE), NULL, MainDlgProc );
  56.     
  57.     return TRUE;
  58. }
  59.  
  60.  
  61.  
  62.  
  63.  
  64. //-----------------------------------------------------------------------------
  65. // Name: MainDlgProc()
  66. // Desc: Handles dialog messages
  67. //-----------------------------------------------------------------------------
  68. INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  69. {
  70.     switch( msg ) 
  71.     {
  72.         case WM_INITDIALOG:
  73.             OnInitDialog( hDlg );
  74.             break;
  75.         
  76.         case WM_COMMAND:
  77.             switch( LOWORD(wParam) )
  78.             {
  79.                 case IDCANCEL:
  80.                     EndDialog( hDlg, 0 ); 
  81.                     break;
  82.  
  83.                 case IDC_EXCLUSIVE:
  84.                 case IDC_NONEXCLUSIVE:
  85.                 case IDC_FOREGROUND:
  86.                 case IDC_BACKGROUND:
  87.                 case IDC_IMMEDIATE:
  88.                 case IDC_BUFFERED:
  89.                     UpdateUI( hDlg );
  90.                     break;
  91.  
  92.                 case IDM_CREATEDEVICE:
  93.                 case IDM_RELEASEDEVICE:
  94.                 case IDC_CREATEDEVICE:
  95.                     if( NULL == g_pMouse )
  96.                     {                    
  97.                         if( FAILED( OnCreateDevice( hDlg ) ) )
  98.                         {
  99.                             MessageBox( hDlg, _T("CreateDevice() failed. ")
  100.                                               _T("The sample will now exit. "), 
  101.                                               _T("Mouse"), MB_ICONERROR | MB_OK );
  102.                             FreeDirectInput();
  103.                         }
  104.  
  105.                         SetFocus( GetDlgItem( hDlg, IDC_CREATEDEVICE ) );
  106.                     }
  107.                     else
  108.                     {
  109.                         FreeDirectInput();
  110.                     }
  111.  
  112.                     UpdateUI( hDlg );
  113.                     break;
  114.  
  115.                 default:
  116.                     return FALSE; // Message not handled 
  117.             }       
  118.             break;
  119.  
  120.         case WM_ENTERMENULOOP:
  121.             // Release the device, so if we are in exclusive mode the 
  122.             // cursor will reappear
  123.             if( g_pMouse )
  124.             {
  125.                 g_pMouse->Unacquire();
  126.                 KillTimer( hDlg, 0 );  // Stop timer, so device is not re-acquired
  127.                 SetDlgItemText( hDlg, IDC_DATA, TEXT("Unacquired") );
  128.             }
  129.             break;
  130.  
  131.         case WM_EXITMENULOOP:
  132.             // Make sure the device is acquired when coming out of a menu loop
  133.             if( g_pMouse )
  134.             {
  135.                 g_pMouse->Acquire();
  136.                 SetTimer( hDlg, 0, 1000 / 12, NULL ); // Start timer again
  137.             }
  138.             break;
  139.  
  140.         case WM_ACTIVATE:
  141.             if( WA_INACTIVE != wParam && g_pMouse )
  142.             {
  143.                 // Make sure the device is acquired, if we are gaining focus.
  144.                 g_pMouse->Acquire();
  145.             }
  146.             break;
  147.         
  148.         case WM_TIMER:
  149.             // Update the input device every timer message
  150.             {
  151.                 BOOL bImmediate = ( IsDlgButtonChecked( hDlg, IDC_IMMEDIATE  ) == BST_CHECKED );
  152.  
  153.                 if( bImmediate )
  154.                 {
  155.                     if( FAILED( ReadImmediateData( hDlg ) ) )
  156.                     {
  157.                         KillTimer( hDlg, 0 );    
  158.                         MessageBox( NULL, _T("Error Reading Input State. ")
  159.                                           _T("The sample will now exit. "), 
  160.                                           _T("Mouse"), MB_ICONERROR | MB_OK );
  161.                         EndDialog( hDlg, TRUE ); 
  162.                     }
  163.                 }
  164.                 else
  165.                 {
  166.                     if( FAILED( ReadBufferedData( hDlg ) ) )
  167.                     {
  168.                         KillTimer( hDlg, 0 );    
  169.                         MessageBox( NULL, _T("Error Reading Input State. ")
  170.                                           _T("The sample will now exit. "), 
  171.                                           _T("Mouse"), MB_ICONERROR | MB_OK );
  172.                         EndDialog( hDlg, TRUE ); 
  173.                     }
  174.                 }
  175.             }
  176.             break;
  177.         
  178.         case WM_DESTROY:
  179.             // Cleanup everything
  180.             KillTimer( hDlg, 0 );    
  181.             FreeDirectInput();    
  182.             break;
  183.  
  184.         default:
  185.             return FALSE; // Message not handled 
  186.     }
  187.  
  188.     return TRUE; // Message handled 
  189. }
  190.  
  191.  
  192.  
  193.  
  194. //-----------------------------------------------------------------------------
  195. // Name: OnInitDialog()
  196. // Desc: Initialize the DirectInput variables.
  197. //-----------------------------------------------------------------------------
  198. HRESULT OnInitDialog( HWND hDlg )
  199. {
  200.     // Load the icon
  201. #ifdef _WIN64
  202.     HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE );
  203. #else
  204.     HINSTANCE hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE );
  205. #endif
  206.     HICON hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN ) );
  207.  
  208.     // Set the icon for this dialog.
  209.     PostMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM) hIcon );  // Set big icon
  210.     PostMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );  // Set small icon
  211.  
  212.     // Check the 'exclusive', 'foreground', and 'immediate' buttons by default. 
  213.     CheckRadioButton( hDlg, IDC_EXCLUSIVE,  IDC_NONEXCLUSIVE, IDC_EXCLUSIVE );
  214.     CheckRadioButton( hDlg, IDC_FOREGROUND, IDC_BACKGROUND,   IDC_FOREGROUND );
  215.     CheckRadioButton( hDlg, IDC_IMMEDIATE,  IDC_BUFFERED,     IDC_IMMEDIATE );
  216.  
  217.     UpdateUI( hDlg );
  218.  
  219.     return S_OK;
  220. }
  221.  
  222.  
  223.  
  224.  
  225. //-----------------------------------------------------------------------------
  226. // Name: UpdateUI()
  227. // Desc: Enables/disables the UI, and sets the dialog behavior text based on the UI
  228. //-----------------------------------------------------------------------------
  229. VOID UpdateUI( HWND hDlg )
  230. {
  231.     TCHAR   strExcepted[2048];
  232.     BOOL    bExclusive;
  233.     BOOL    bForeground;
  234.     BOOL    bImmediate;
  235.  
  236.     // Detrimine where the buffer would like to be allocated 
  237.     bExclusive         = ( IsDlgButtonChecked( hDlg, IDC_EXCLUSIVE  ) == BST_CHECKED );
  238.     bForeground        = ( IsDlgButtonChecked( hDlg, IDC_FOREGROUND ) == BST_CHECKED );
  239.     bImmediate         = ( IsDlgButtonChecked( hDlg, IDC_IMMEDIATE  ) == BST_CHECKED );
  240.  
  241.     if( g_pMouse )
  242.     {
  243.         SetDlgItemText( hDlg, IDC_CREATEDEVICE, TEXT("&Release Device") );
  244.         EnableMenuItem( GetMenu( hDlg ), IDM_RELEASEDEVICE, MF_ENABLED );
  245.         EnableMenuItem( GetMenu( hDlg ), IDM_CREATEDEVICE,  MF_GRAYED );
  246.         SetDlgItemText( hDlg, IDC_DATA, TEXT("") );
  247.  
  248.         EnableWindow( GetDlgItem( hDlg, IDC_EXCLUSIVE    ), FALSE );
  249.         EnableWindow( GetDlgItem( hDlg, IDC_NONEXCLUSIVE ), FALSE );
  250.         EnableWindow( GetDlgItem( hDlg, IDC_FOREGROUND   ), FALSE );
  251.         EnableWindow( GetDlgItem( hDlg, IDC_BACKGROUND   ), FALSE );
  252.         EnableWindow( GetDlgItem( hDlg, IDC_IMMEDIATE    ), FALSE );
  253.         EnableWindow( GetDlgItem( hDlg, IDC_BUFFERED     ), FALSE );
  254.  
  255.         if( bExclusive )
  256.             SetDlgItemText( hDlg, IDC_HELP_TEXT, 
  257.                             TEXT("Press Enter to release the mouse device, ") \
  258.                             TEXT("and display the cursor again.") );
  259.     }
  260.     else
  261.     {
  262.         SetDlgItemText( hDlg, IDC_CREATEDEVICE, TEXT("&Create Device") );
  263.         EnableMenuItem( GetMenu( hDlg ), IDM_RELEASEDEVICE, MF_GRAYED );
  264.         EnableMenuItem( GetMenu( hDlg ), IDM_CREATEDEVICE,  MF_ENABLED );
  265.         SetDlgItemText( hDlg, IDC_DATA, TEXT("Device not created. Choose settings and click 'Create Device' then move mouse to see results") );   
  266.         SetDlgItemText( hDlg, IDC_HELP_TEXT, TEXT("") );
  267.  
  268.         EnableWindow( GetDlgItem( hDlg, IDC_EXCLUSIVE    ), TRUE );
  269.         EnableWindow( GetDlgItem( hDlg, IDC_NONEXCLUSIVE ), TRUE );
  270.         EnableWindow( GetDlgItem( hDlg, IDC_FOREGROUND   ), TRUE );
  271.         EnableWindow( GetDlgItem( hDlg, IDC_BACKGROUND   ), TRUE );
  272.         EnableWindow( GetDlgItem( hDlg, IDC_IMMEDIATE    ), TRUE );
  273.         EnableWindow( GetDlgItem( hDlg, IDC_BUFFERED     ), TRUE );
  274.     }
  275.  
  276.     // Figure what the user should expect based on the dialog choice
  277.     if( !bForeground && bExclusive )
  278.     {
  279.         _tcscpy( strExcepted, TEXT("For security reasons, background exclusive ") \
  280.                              TEXT("mouse access is not allowed.\n\n") );
  281.     }
  282.     else
  283.     {
  284.         if( bForeground )
  285.         {
  286.             _tcscpy( strExcepted, TEXT("Foreground cooperative level means that the ") \
  287.                                  TEXT("application has access to data only when in the ") \
  288.                                  TEXT("foreground or, in other words, has the input focus. ") \
  289.                                  TEXT("If the application moves to the background, ") \
  290.                                  TEXT("the device is automatically unacquired, or made ") \
  291.                                  TEXT("unavailable.\n\n") );
  292.         }
  293.         else
  294.         {
  295.             _tcscpy( strExcepted, TEXT("Background cooperative level really means ") \
  296.                                  TEXT("foreground and background. A device with a ") \
  297.                                  TEXT("background cooperative level can be acquired ") \
  298.                                  TEXT("and used by an application at any time.\n\n") );
  299.         }
  300.  
  301.         if( bExclusive )
  302.         {
  303.             _tcscat( strExcepted, TEXT("Exclusive mode prevents other applications from ") \
  304.                                  TEXT("also acquiring the device exclusively. The fact ") \
  305.                                  TEXT("that your application is using a device at the ") \
  306.                                  TEXT("exclusive level does not mean that other ") \
  307.                                  TEXT("applications cannot get data from the device. ") \
  308.                                  TEXT("Windows itself requires exclusive access to the ") \
  309.                                  TEXT("mouse because mouse events such as a click on ") \
  310.                                  TEXT("an inactive window could force an application ") \
  311.                                  TEXT("to unacquire the device, with potentially harmful ") \
  312.                                  TEXT("results, such as a loss of data from the input ") \
  313.                                  TEXT("buffer. Therefore, when an application has ") \
  314.                                  TEXT("exclusive access to the mouse, Windows is not ") \
  315.                                  TEXT("allowed any access at all. No mouse messages are ") \
  316.                                  TEXT("generated. A further side effect is that the ") \
  317.                                  TEXT("cursor disappears. When accessing the menu, the sample ") \
  318.                                  TEXT("releases the mouse so the mouse is displayed again.\n\n"));
  319.         }
  320.         else
  321.         {
  322.             _tcscat( strExcepted, TEXT("Nonexclusive mode means that other applications ") \
  323.                                  TEXT("can acquire device in exclusive or nonexclusive mode.\n\n"));
  324.         }
  325.  
  326.         if( bImmediate )
  327.         {
  328.             _tcscat( strExcepted, TEXT("Immediate data is a snapshot of the current ") \
  329.                                  TEXT("state of a device. It provides no data about ") \
  330.                                  TEXT("what has happened with the device since the ") \
  331.                                  TEXT("last call, apart from implicit information that ") \
  332.                                  TEXT("you can derive by comparing the current state with ") \
  333.                                  TEXT("the last one. Events in between calls are lost.\n\n") );
  334.         }
  335.         else
  336.         {
  337.             _tcscat( strExcepted, TEXT("Buffered data is a record of events that are stored ") \
  338.                                  TEXT("until an application retrieves them. With buffered ") \
  339.                                  TEXT("data, events are stored until you are ready to deal ") \
  340.                                  TEXT("with them. If the buffer overflows, new data is lost.\n\n") );                             
  341.         }
  342.  
  343.         _tcscat( strExcepted, TEXT("The sample will read the mouse 12 times a second. ") \
  344.                              TEXT("Typically an application would poll the mouse ") \
  345.                              TEXT("much faster than this, but this slow rate is simply ") \
  346.                              TEXT("for the purposes of demonstration.") );
  347.     }
  348.  
  349.     // Tell the user what to expect
  350.     SetDlgItemText( hDlg, IDC_BEHAVIOR, strExcepted );
  351. }
  352.  
  353.  
  354.  
  355.  
  356. //-----------------------------------------------------------------------------
  357. // Name: OnCreateDevice()
  358. // Desc: Setups a the mouse device using the flags from the dialog.
  359. //-----------------------------------------------------------------------------
  360. HRESULT OnCreateDevice( HWND hDlg )
  361. {
  362.     HRESULT hr;
  363.     BOOL    bExclusive;
  364.     BOOL    bForeground;
  365.     BOOL    bImmediate;
  366.     DWORD   dwCoopFlags;
  367.  
  368.     // Cleanup any previous call first
  369.     KillTimer( hDlg, 0 );    
  370.     FreeDirectInput();
  371.  
  372.     // Detrimine where the buffer would like to be allocated 
  373.     bExclusive         = ( IsDlgButtonChecked( hDlg, IDC_EXCLUSIVE  ) == BST_CHECKED );
  374.     bForeground        = ( IsDlgButtonChecked( hDlg, IDC_FOREGROUND ) == BST_CHECKED );
  375.     bImmediate         = ( IsDlgButtonChecked( hDlg, IDC_IMMEDIATE  ) == BST_CHECKED );
  376.  
  377.     if( bExclusive )
  378.         dwCoopFlags = DISCL_EXCLUSIVE;
  379.     else
  380.         dwCoopFlags = DISCL_NONEXCLUSIVE;
  381.  
  382.     if( bForeground )
  383.         dwCoopFlags |= DISCL_FOREGROUND;
  384.     else
  385.         dwCoopFlags |= DISCL_BACKGROUND;
  386.  
  387.     // Create a DInput object
  388.     if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, 
  389.                                          IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) )
  390.         return hr;
  391.     
  392.     // Obtain an interface to the system mouse device.
  393.     if( FAILED( hr = g_pDI->CreateDevice( GUID_SysMouse, &g_pMouse, NULL ) ) )
  394.         return hr;
  395.     
  396.     // Set the data format to "mouse format" - a predefined data format 
  397.     //
  398.     // A data format specifies which controls on a device we
  399.     // are interested in, and how they should be reported.
  400.     //
  401.     // This tells DirectInput that we will be passing a
  402.     // DIMOUSESTATE2 structure to IDirectInputDevice::GetDeviceState.
  403.     if( FAILED( hr = g_pMouse->SetDataFormat( &c_dfDIMouse2 ) ) )
  404.         return hr;
  405.     
  406.     // Set the cooperativity level to let DirectInput know how
  407.     // this device should interact with the system and with other
  408.     // DirectInput applications.
  409.     hr = g_pMouse->SetCooperativeLevel( hDlg, dwCoopFlags );
  410.     if( hr == DIERR_UNSUPPORTED && !bForeground && bExclusive )
  411.     {
  412.         FreeDirectInput();
  413.         MessageBox( hDlg, _T("SetCooperativeLevel() returned DIERR_UNSUPPORTED.\n")
  414.                           _T("For security reasons, background exclusive mouse\n")
  415.                           _T("access is not allowed."), 
  416.                           _T("Mouse"), MB_OK );
  417.         return S_OK;
  418.     }
  419.  
  420.     if( FAILED(hr) )
  421.         return hr;
  422.  
  423.     if( !bImmediate )
  424.     {
  425.         // IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
  426.         //
  427.         // DirectInput uses unbuffered I/O (buffer size = 0) by default.
  428.         // If you want to read buffered data, you need to set a nonzero
  429.         // buffer size.
  430.         //
  431.         // Set the buffer size to SAMPLE_BUFFER_SIZE (defined above) elements.
  432.         //
  433.         // The buffer size is a DWORD property associated with the device.
  434.         DIPROPDWORD dipdw;
  435.         dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
  436.         dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  437.         dipdw.diph.dwObj        = 0;
  438.         dipdw.diph.dwHow        = DIPH_DEVICE;
  439.         dipdw.dwData            = SAMPLE_BUFFER_SIZE; // Arbitary buffer size
  440.  
  441.         if( FAILED( hr = g_pMouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) )
  442.             return hr;
  443.     }
  444.  
  445.     // Acquire the newly created device
  446.     g_pMouse->Acquire();
  447.  
  448.     // Set a timer to go off 12 times a second, to read input
  449.     // Note: Typically an application would poll the mouse
  450.     //       much faster than this, but this slow rate is simply 
  451.     //       for the purposes of demonstration
  452.     SetTimer( hDlg, 0, 1000 / 12, NULL );
  453.  
  454.     return S_OK;
  455. }
  456.  
  457.  
  458.  
  459.  
  460. //-----------------------------------------------------------------------------
  461. // Name: ReadImmediateData()
  462. // Desc: Read the input device's state when in immediate mode and display it.
  463. //-----------------------------------------------------------------------------
  464. HRESULT ReadImmediateData( HWND hDlg )
  465. {
  466.     HRESULT       hr;
  467.     TCHAR         strNewText[128] = TEXT("");   // Output string
  468.     DIMOUSESTATE2 dims2;      // DirectInput mouse state structure
  469.  
  470.     if( NULL == g_pMouse ) 
  471.         return S_OK;
  472.     
  473.     // Get the input's device state, and put the state in dims
  474.     ZeroMemory( &dims2, sizeof(dims2) );
  475.     hr = g_pMouse->GetDeviceState( sizeof(DIMOUSESTATE2), &dims2 );
  476.     if( FAILED(hr) ) 
  477.     {
  478.         // DirectInput may be telling us that the input stream has been
  479.         // interrupted.  We aren't tracking any state between polls, so
  480.         // we don't have any special reset that needs to be done.
  481.         // We just re-acquire and try again.
  482.         
  483.         // If input is lost then acquire and keep trying 
  484.         hr = g_pMouse->Acquire();
  485.         while( hr == DIERR_INPUTLOST ) 
  486.             hr = g_pMouse->Acquire();
  487.  
  488.         // Update the dialog text 
  489.         if( hr == DIERR_OTHERAPPHASPRIO || 
  490.             hr == DIERR_NOTACQUIRED ) 
  491.             SetDlgItemText( hDlg, IDC_DATA, TEXT("Unacquired") );
  492.  
  493.         // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
  494.         // may occur when the app is minimized or in the process of 
  495.         // switching, so just try again later 
  496.         return S_OK; 
  497.     }
  498.     
  499.     // The dims structure now has the state of the mouse, so 
  500.     // display mouse coordinates (x, y, z) and buttons.
  501.     _stprintf( strNewText, TEXT("(X=% 3.3d, Y=% 3.3d, Z=% 3.3d) B0=%c B1=%c B2=%c B3=%c B4=%c B5=%c B6=%c B7=%c"),
  502.                          dims2.lX, dims2.lY, dims2.lZ,
  503.                         (dims2.rgbButtons[0] & 0x80) ? '1' : '0',
  504.                         (dims2.rgbButtons[1] & 0x80) ? '1' : '0',
  505.                         (dims2.rgbButtons[2] & 0x80) ? '1' : '0',
  506.                         (dims2.rgbButtons[3] & 0x80) ? '1' : '0',
  507.                         (dims2.rgbButtons[4] & 0x80) ? '1' : '0',
  508.                         (dims2.rgbButtons[5] & 0x80) ? '1' : '0',
  509.                         (dims2.rgbButtons[6] & 0x80) ? '1' : '0',
  510.                         (dims2.rgbButtons[7] & 0x80) ? '1' : '0');
  511.  
  512.     // Get the old text in the text box
  513.     TCHAR strOldText[128];
  514.     GetDlgItemText( hDlg, IDC_DATA, strOldText, 127 );
  515.     
  516.     // If nothing changed then don't repaint - avoid flicker
  517.     if( 0 != lstrcmp( strOldText, strNewText ) ) 
  518.         SetDlgItemText( hDlg, IDC_DATA, strNewText );
  519.     
  520.     return S_OK;
  521. }
  522.  
  523.  
  524.  
  525.  
  526. //-----------------------------------------------------------------------------
  527. // Name: ReadBufferedData()
  528. // Desc: Read the input device's state when in buffered mode and display it.
  529. //-----------------------------------------------------------------------------
  530. HRESULT ReadBufferedData( HWND hDlg )
  531. {
  532.     TCHAR              strNewText[128] = TEXT(""); 
  533.     DIDEVICEOBJECTDATA didod[ SAMPLE_BUFFER_SIZE ];  // Receives buffered data 
  534.     DWORD              dwElements;
  535.     DWORD              i;
  536.     HRESULT            hr;
  537.  
  538.     if( NULL == g_pMouse ) 
  539.         return S_OK;
  540.     
  541.     dwElements = SAMPLE_BUFFER_SIZE;
  542.     hr = g_pMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),
  543.                                      didod, &dwElements, 0 );
  544.     if( hr != DI_OK ) 
  545.     {
  546.         // We got an error or we got DI_BUFFEROVERFLOW.
  547.         //
  548.         // Either way, it means that continuous contact with the
  549.         // device has been lost, either due to an external
  550.         // interruption, or because the buffer overflowed
  551.         // and some events were lost.
  552.         //
  553.         // Consequently, if a button was pressed at the time
  554.         // the buffer overflowed or the connection was broken,
  555.         // the corresponding "up" message might have been lost.
  556.         //
  557.         // But since our simple sample doesn't actually have
  558.         // any state associated with button up or down events,
  559.         // there is no state to reset.  (In a real game, ignoring
  560.         // the buffer overflow would result in the game thinking
  561.         // a key was held down when in fact it isn't; it's just
  562.         // that the "up" event got lost because the buffer
  563.         // overflowed.)
  564.         //
  565.         // If we want to be cleverer, we could do a
  566.         // GetDeviceState() and compare the current state
  567.         // against the state we think the device is in,
  568.         // and process all the states that are currently
  569.         // different from our private state.
  570.         hr = g_pMouse->Acquire();
  571.         while( hr == DIERR_INPUTLOST ) 
  572.             hr = g_pMouse->Acquire();
  573.  
  574.         // Update the dialog text 
  575.         if( hr == DIERR_OTHERAPPHASPRIO || 
  576.             hr == DIERR_NOTACQUIRED ) 
  577.             SetDlgItemText( hDlg, IDC_DATA, TEXT("Unacquired") );
  578.  
  579.         // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
  580.         // may occur when the app is minimized or in the process of 
  581.         // switching, so just try again later 
  582.         return S_OK; 
  583.     }
  584.  
  585.     if( FAILED(hr) )  
  586.         return hr;
  587.  
  588.     // Study each of the buffer elements and process them.
  589.     //
  590.     // Since we really don't do anything, our "processing"
  591.     // consists merely of squirting the name into our
  592.     // local buffer.
  593.     for( i = 0; i < dwElements; i++ ) 
  594.     {
  595.         // this will display then scan code of the key
  596.         // plus a 'D' - meaning the key was pressed 
  597.         //   or a 'U' - meaning the key was released
  598.         switch( didod[ i ].dwOfs )
  599.         {
  600.             case DIMOFS_BUTTON0:
  601.                 _tcscat( strNewText, TEXT("B0") );
  602.                 break;
  603.  
  604.             case DIMOFS_BUTTON1:
  605.                 _tcscat( strNewText, TEXT("B1") );
  606.                 break;
  607.  
  608.             case DIMOFS_BUTTON2:
  609.                 _tcscat( strNewText, TEXT("B2") );
  610.                 break;
  611.  
  612.             case DIMOFS_BUTTON3:
  613.                 _tcscat( strNewText, TEXT("B3") );
  614.                 break;
  615.  
  616.             case DIMOFS_X:
  617.                 _tcscat( strNewText, TEXT("X") );
  618.                 break;
  619.  
  620.             case DIMOFS_Y:
  621.                 _tcscat( strNewText, TEXT("Y") );
  622.                 break;
  623.  
  624.             case DIMOFS_Z:
  625.                 _tcscat( strNewText, TEXT("Z") );
  626.                 break;
  627.  
  628.             default:
  629.                 _tcscat( strNewText, TEXT("") );
  630.         }
  631.  
  632.         switch( didod[ i ].dwOfs )
  633.         {
  634.             case DIMOFS_BUTTON0:
  635.             case DIMOFS_BUTTON1:
  636.             case DIMOFS_BUTTON2:
  637.             case DIMOFS_BUTTON3:
  638.                 if( didod[ i ].dwData & 0x80 )
  639.                     _tcscat( strNewText, TEXT("U ") );
  640.                 else
  641.                     _tcscat( strNewText, TEXT("D ") );
  642.                 break;
  643.  
  644.             case DIMOFS_X:
  645.             case DIMOFS_Y:
  646.             case DIMOFS_Z:
  647.             {
  648.                 TCHAR strCoordValue[20];
  649.                 wsprintf( strCoordValue, TEXT("%d "), didod[ i ].dwData );
  650.                 _tcscat( strNewText, strCoordValue );
  651.                 break;
  652.             }
  653.         }
  654.     }
  655.  
  656.     // Get the old text in the text box
  657.     TCHAR strOldText[128];
  658.     GetDlgItemText( hDlg, IDC_DATA, strOldText, 127 );
  659.  
  660.     // If nothing changed then don't repaint - avoid flicker
  661.     if( 0 != lstrcmp( strOldText, strNewText ) ) 
  662.         SetDlgItemText( hDlg, IDC_DATA, strNewText );    
  663.  
  664.     return S_OK;
  665. }
  666.  
  667.  
  668.  
  669.  
  670. //-----------------------------------------------------------------------------
  671. // Name: FreeDirectInput()
  672. // Desc: Initialize the DirectInput variables.
  673. //-----------------------------------------------------------------------------
  674. VOID FreeDirectInput()
  675. {
  676.     // Unacquire the device one last time just in case 
  677.     // the app tried to exit while the device is still acquired.
  678.     if( g_pMouse ) 
  679.         g_pMouse->Unacquire();
  680.     
  681.     // Release any DirectInput objects.
  682.     SAFE_RELEASE( g_pMouse );
  683.     SAFE_RELEASE( g_pDI );
  684. }
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.